Skip to content

grass.script: Add locking to init #5591

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 26, 2025

Conversation

wenzeslaus
Copy link
Member

The function gs.setup.init can now optionally lock the mapset and unlock when exiting the context or with call to finish (both free function or bound method). This keeps the current state of not locking as a default, i.e., the locking is opt-in, so multiple session are responsibility of the user just like running multiple processes within one mapset.

Importantly, this brings feature parity with the grass command to Python, and makes it possible for users to use the mapset locking from Python.

The PID used is the the current process ID which is already used for variable GIS_LOCK in init. The underlying locking (but not unlocking) functionality is the same one as used for the main grass command thanks to a previous refactoring of locking from lib/init/grass.py to grass.app.data.

The tests are included, but the thing about testing this is that when lock is found lib/init/lock.c (etc/lock) waits for a second before proceeding to check the file content. This makes each test with existing lock to take at least one second. There is currently six tests like that. The lock program wants to read the PID written to the lock file, so it waits for one second to ensure that another process wrote the content to the file. Without a lock preset, the operation is fast.

The function _gs.setup.init_ can now optionally lock the mapset and unlock when exiting the context or with call to finish (both free function or bound method). This keeps the current state of not locking as a default, i.e., the locking is opt-in, so multiple session are responsibility of the user just like running multiple processes within one mapset.

The PID used is the the current process ID which is already used for variable GIS_LOCK in init. The underlying locking (but not unlocking) functionality is the same one as used for the main _grass_ command thanks to a previous refactoring of locking from lib/init/grass.py to _grass.app.data_.
@wenzeslaus wenzeslaus self-assigned this Apr 25, 2025
@github-actions github-actions bot added Python Related code is in Python libraries tests Related to Test Suite labels Apr 25, 2025
@wenzeslaus
Copy link
Member Author

@joao-krauchenco-mottu Thanks for the review. First in this repo from what I can tell. That's great. I appreciate any feedback.

@wenzeslaus wenzeslaus merged commit 70bc66d into OSGeo:main Apr 26, 2025
28 checks passed
@wenzeslaus wenzeslaus deleted the add-locking-to-python-api branch April 26, 2025 15:15
@github-actions github-actions bot added this to the 8.5.0 milestone Apr 26, 2025
wenzeslaus added a commit that referenced this pull request May 1, 2025
This change introduces a timeout parameter in CLI which is enabled by default and makes GRASS wait if the mapset is locked.

Additionally, this adds timeout parameter also to the Python API, so this keeps feature parity between the two (with locking and force lock removal already in place since #5591). The automatic tests are using the Python API, but they are limited as they don't use multiple threads or processes.

This also introduces new subcommands to the experimental execution of the grass.app with CLI API using `python -m grass.app` from #5590. Specifically, lock and unlock subcommands are now available and can be used for testing (compensating for the limited automatic tests), fixing lock situations, and by external applications which need to persistently lock mapset without using the Python API directly. Subcommands are added to the first level, but could eventually be under a project or mapset subcommand.

Notably, the locking is disabled on Windows, so test is disabled for Windows.

The timeout implementation actually measures the elapsed time in addition to counting the theoretically waited time. While counting clearly ends the loop, the elapsed time may be significantly higher for some timeouts given that the lock process execution takes a second to execute when the mapset is locked as it waits (for a second) to make sure a PID is written to the file but the other process.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libraries Python Related code is in Python tests Related to Test Suite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants